package com.gxa.customer.security.filter;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.gxa.common.commons.R;
import com.gxa.common.pojo.SysUser;
import com.gxa.customer.security.common.SecurityUser;
import com.gxa.common.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.UUID;

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    //@Autowired不用自动注入，XXX的时候才注入依赖进来，所以用构造方法更合适
    private RedisTemplate redisTemplate;
    //@Autowired不用自动注入，XXX的时候才注入依赖进来，所以用构造方法更合适
    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager,RedisTemplate redisTemplate ) {
        this.redisTemplate = redisTemplate;
        this.authenticationManager = authenticationManager;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login", "POST"));
    }

    //1.获取表单提交用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            //1.获取到用户账号和密码
            //String username = request.getParameter("username");
            //String password = request.getParameter("password");
            //1.获取到用户账号和密码JSON->Class
            //SysUser user =JsonObject.parseObject(request.getInputStream(), SysUser.class);
            SysUser user = new ObjectMapper().readValue(request.getInputStream(), SysUser.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    //2.认证成功后的调用的方法
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //认证成功，得到认证成功之后的用户信息
        SecurityUser user = (SecurityUser)authResult.getPrincipal();
        //1.登录成功后，后端生成token令牌。
        String authorization =  JwtUtils.createJwt(UUID.randomUUID().toString(),JwtUtils.ISS, user.getCurrentUserInfo().getUsername(),JwtUtils.TTMILLIS);
        //2.存入redis中
        redisTemplate.opsForList().leftPushAll(user.getCurrentUserInfo().getUsername(),user.getPermissionValueList());

        //返回
        R r = new R();
        r.setCode(200);
        r.setMsg("认证成功");

        //3.通过响应头返回给前端
        response.setHeader("Authorization",authorization);
        //4.暴露响应头
        response.setHeader("Access-Control-Expose-Headers","Authorization");
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONObject.toJSONString(r));
    }

    //3.认证失败后的调用的方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        R r = new R();
        r.setCode(500);
        r.setMsg("认证失败");
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONObject.toJSONString(r));
        response.getWriter().flush();
        response.getWriter().close();
    }
}